--[[
title: 表相关函数
description: 表管理, 面向对象实现
]]

local __G__ = {};

-- 获取表字段
function commonlib.getfield(f, G)
	if(not f) then return end
	local v = G or __G__;
	for w in string.gmatch(f, "([%w_]+)(.?)") do
		if(type(v) ~= "table") then return nil end
		v = v[w];
	end
    return v;
end

-- 设置表字段
function commonlib.setfield(f, v, G)
	if(not f) then return end
	local t = G or __G__;
	for w, d in string.gmatch(f, "([%w_]+)(.?)") do
		if d == "." then
			t[w] = t[w] or {};
			t = t[w];
		else
			t[w] = v;
		end
	end
end

-- 逆序表
function commonlib.reversetable(t)
    local size = #t;
    local half_size = math.floor(size / 2);
    for i = 1, half_size do
        t[i], t[size - i + 1] = t[size - i + 1], t[i];
    end
    return t;
end

-- 清空表
local clearcachetable = {};
function commonlib.cleartable(t)
	if (type(t) ~= "table") then return end

	local index = 0;
	for key in pairs(t) do
		index = index + 1;
		clearcachetable[index] = key;
	end
	for i = 1, index do
		t[clearcachetable[i]] = nil;
	end
end

-- 获取表key列表
local cache_keys = {};
function commonlib.keys(t)
	local size = #cache_keys;
	for i = 1, size do cache_keys[i] = nil end
	local index = 0;
	for key in pairs(t) do
		index = index + 1;
		cache_keys[index] = key;
	end
	return cache_keys, index;
end

-- 获取表value列表
local cache_values = {};
commonlib.values = function(t)
	local size = #cache_values;
	for i = 1, size do cache_values[i] = nil end
	local index = 0;
	for _, val in pairs(t) do
		index = index + 1;
		cache_values[index] = val;
	end
	return cache_values, index;
end

-- 获取表
function commonlib.gettable(f, G)
	if(not f) then return end
	local t = G or __G__;
	for w in string.gmatch(f, "([%w_]+)(.?)") do
		t[w] = t[w] or {};
		t = t[w];
	end
	return t;
end

-- 深拷贝含元表
function commonlib.deepcopy(obj)
    local lookup_table = {}
    local function _copy(object)
        if type(object) ~= "table" then
            return object
        elseif lookup_table[object] then
            return lookup_table[object]
        end
        local new_table = {}
        lookup_table[object] = new_table
        for index, value in pairs(object) do
            new_table[_copy(index)] = _copy(value)
        end
        return setmetatable(new_table, getmetatable(object))
    end
    return _copy(obj)
end

-- 深拷贝不含元表
function commonlib.copy(obj)
	local lookup_table = {}
    local function _copy(object)
        if type(object) ~= "table" then
            return object
        elseif lookup_table[object] then
            return lookup_table[object]
        end
        local new_table = {}
        lookup_table[object] = new_table
        for index, value in pairs(object) do
            new_table[_copy(index)] = _copy(value)
        end
        return new_table;
    end
    return _copy(obj)
end

-- 深拷贝源表字段
function commonlib.partialcopy(dest_obj, src_obj)
    local function _assign(dest, src)
	    if type(src) == "table" and type(dest) =="table"  then
			for key, value in pairs(src) do
				if(type(value) =="table") then
					if(type(dest[key]) == "table") then
						_assign(dest[key], value);
					else
						dest[key] = {};
						_assign(dest[key], value);
					end
				else
					dest[key] = value;
				end
			end
        end
    end
    return _assign(dest_obj, src_obj)
end

-- 深拷贝目标表不存在字段
function commonlib.mincopy(dest_obj, src_obj)
    local function _assign(dest, src)
	    if type(src) =="table"  and type(dest) =="table"  then
			for key, value in pairs(src) do
				if(dest[key] == nil) then
					if(type(value) =="table") then
						dest[key] = {};
						_assign(dest[key], value);
					else
						dest[key] = value
					end
				end
			end
        end
    end
    return _assign(dest_obj, src_obj)
end

-- 绑定函数到表
function commonlib.bind(fn, self)
    return function(...) return fn(self, ...) end
end

-- 表继承
function commonlib.inherit(base_class, derived_class)
	base_class = type(base_class) == "table" and base_class or nil;
	derived_class = type(derived_class) == "table" and derived_class or {};

	if (base_class ~= nil) then setmetatable(derived_class, { __index = base_class}) end

	-- this ensures that the base class new function is also called.
    function derived_class.new(_, class_instance)
        class_instance = class_instance or {};

        if(base_class) then
			-- this ensures that the constructor of all base classes are called.
			if(base_class.new~=nil) then
				base_class:new(class_instance);
			end
        end

		setmetatable(class_instance, { __index = derived_class });

		-- please note inside ctor function, parent class virtual functions are not available,since meta table of parent is not set yet. 
		local derived_class_ctor = rawget(derived_class, "ctor");
		if(derived_class_ctor) then derived_class_ctor(class_instance) end

        return class_instance;
    end

    -- Return the class object of the instance
    function derived_class.class()
        return derived_class;
    end

    -- Return the super class object of the instance
    derived_class._super = base_class;

    -- Return true if the caller is an instance of theClass
    function derived_class.isa(theClass)
        local b_isa = false
        local cur_class = derived_class;
        while (nil ~= cur_class) and (false == b_isa) do
            if cur_class == theClass then
                b_isa = true;
            else
                cur_class = cur_class._super;
            end
        end
        return b_isa;
    end

    return derived_class;
end

-- 排序
function commonlib.sort(list, desc)
	local size = #list;
	for i = 1, size do
		for j = i + 1, size do
			if (desc) then
				if (list[i] < list[j]) then
					list[i], list[j] = list[j], list[i];
				end
			else
				if (list[i] > list[j]) then
					list[i], list[j] = list[j], list[i];
				end
			end
		end
	end

	return list;
end

function commonlib.extend(dst_obj, src_obj, keys)
	keys = keys or commonlib.keys(src_obj);
	for _, key in ipairs(keys) do
		local value = src_obj[key];
		dst_obj[key] = type(value) == "function" and commonlib.bind(value, src_obj) or value;
	end
end
